"""
哨兵模式

基本介绍
    作用
        监控redis服务器的运行状态, 可以进行 自动故障转移(failover), 实现高可用
        与 数据库主从 配合使用的机制
    特点
        独立的进程, 每台redis服务器应该至少配置一个哨兵程序
        监控redis主服务器的运行状态
        出现故障后可以向管理员/其他程序发出通知
        针对故障,可以进行自动转移, 并向客户端提供新的访问地址
内部机制 (了解)
    流言协议
        当某个哨兵程序ping 发现监视的主服务器下线后(心跳检测), 会向监听该服务器的其他哨兵询问, 是否确认主服务器下线, 当 确认的哨兵数量 达到要求(配置文件中设置)后, 会确认主服务器下线(客观下线), 然后进入投票环节
    投票协议
        当确认主服务器客观下线后, 哨兵会通过 投票的方式 来授权其中一个哨兵主导故障转移处理
        只有在 大多数哨兵都参加投票 的前提下, 才会进行授权, 比如有5个哨兵, 则需要至少3个哨兵投票才可能授权
        目的是避免出现错误的故障迁移
    建议最低配置
        至少在3台服务器上分别启动至少一个哨兵
        如果只有一台, 则服务器宕机后, 将无法进行故障迁移
        如果只有两台, 一旦一个哨兵挂掉了, 则投票会失败
"""
# python通过哨兵访问Redis主从
# redis-py包中就集成了哨兵功能
from redis.sentinel import Sentinel

# 记录哨兵的ip和端口
setinels = [
    ('192.168.19.137', 26380),
    ('192.168.19.137', 26381),
    ('192.168.19.137', 26382)
]

# 创建哨兵客户端
setinel_client = Sentinel(setinels)

# 记录主数据库别名
service_name = 'mymaster'

# 通过哨兵来获取主数据库客户端
redis_master = setinel_client.master_for(service_name, decode_responses=True)
# print(type(redis_master))

# 通过哨兵来获取从数据库客户端
redis_slave = setinel_client.slave_for(service_name, decode_responses=True)
# print(redis_slave)

# 主数据库读写
mapping = {"大话西游" : 10}
redis_master.zadd('movies', mapping)
score = redis_master.zscore('movies', '大话西游')
print(score)
# redis_master.set("name", "zhangsan")
# print(redis_slave.get("name"))

# 从数据库读
# score = redis_slave.zscore('movies', '大话西游')
# print(score)
# redis_slave.zadd('movies', 7.5, '西红柿首富')  # 从库不能写入, 会报错

# 视图中只有写, 直接选主
# 视图中只有读, 直接选从
# 视图中有读有写, 建议选主
